/*********************************************************************************************
    *   Filename        : app_keyboard.c

    *   Description     :

    *   Author          :

    *   Email           :

    *   Last modifiled  : 2019-07-05 10:09

    *   Copyright:(c)JIELI  2011-2019  @ , All Rights Reserved.
*********************************************************************************************/
#include "system/app_core.h"
#include "system/includes.h"
#include "server/server_core.h"
#include "app_config.h"
#include "app_action.h"
#include "os/os_api.h"
#include "btcontroller_config.h"
#include "btctrler/btctrler_task.h"
#include "config/config_transport.h"
#include "btstack/avctp_user.h"
#include "btstack/btstack_task.h"
#include "bt_common.h"
#include "edr_hid_user.h"
/* #include "code_switch.h" */
/* #include "omsensor/OMSensor_manage.h" */
#include "le_common.h"
#include <stdlib.h>
#include "standard_hid.h"
#include "rcsp_bluetooth.h"
#include "app_charge.h"
#include "app_power_manage.h"
#include "app_chargestore.h"
#include "app_comm_bt.h"

#if(CONFIG_APP_STYLUS_PEN)
#define LOG_TAG_CONST       S_PEN
#define LOG_TAG             "[S_PEN]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"

#if TCFG_AUDIO_ENABLE
#include "tone_player.h"
#include "media/includes.h"
#include "key_event_deal.h"
extern void midi_paly_test(u32 key);
#endif/*TCFG_AUDIO_ENABLE*/

//测试每个interval上行发一包数据
#define  HID_TEST_KEEP_SEND_EN        0//just for test keep data

#define trace_run_debug_val(x)   //log_info("\n## %s: %d,  0x%04x ##\n",__FUNCTION__,__LINE__,x)

//---------------------------------------------------------------------
#if SNIFF_MODE_RESET_ANCHOR
#define SNIFF_MODE_TYPE               SNIFF_MODE_ANCHOR
#define SNIFF_CNT_TIME                1/////<空闲?S之后进入sniff模式

#define SNIFF_MAX_INTERVALSLOT        16
#define SNIFF_MIN_INTERVALSLOT        16
#define SNIFF_ATTEMPT_SLOT            2
#define SNIFF_TIMEOUT_SLOT            1
#define SNIFF_CHECK_TIMER_PERIOD      200
#else

#define SNIFF_MODE_TYPE               SNIFF_MODE_DEF
#define SNIFF_CNT_TIME                5/////<空闲?S之后进入sniff模式

#define SNIFF_MAX_INTERVALSLOT        800
#define SNIFF_MIN_INTERVALSLOT        100
#define SNIFF_ATTEMPT_SLOT            4
#define SNIFF_TIMEOUT_SLOT            1
#define SNIFF_CHECK_TIMER_PERIOD      1000
#endif

//默认配置
static const edr_sniff_par_t S_pen_sniff_param = {
    .sniff_mode = SNIFF_MODE_TYPE,
    .cnt_time = SNIFF_CNT_TIME,
    .max_interval_slots = SNIFF_MAX_INTERVALSLOT,
    .min_interval_slots = SNIFF_MIN_INTERVALSLOT,
    .attempt_slots = SNIFF_ATTEMPT_SLOT,
    .timeout_slots = SNIFF_TIMEOUT_SLOT,
    .check_timer_period = SNIFF_CHECK_TIMER_PERIOD,
};

typedef enum {
    HID_MODE_NULL = 0,
    HID_MODE_EDR,
    HID_MODE_BLE,
    HID_MODE_INIT = 0xff
} bt_mode_e;

#define KEYBOARD_REPORT_ID          0x1//默认report_data修改为4/5/6
#define COUSTOM_CONTROL_REPORT_ID   0x3
#define MOUSE_POINT_REPORT_ID       0x6


static bt_mode_e bt_hid_mode;
static volatile u8 is_S_pen_active = 0;//1-临界点,系统不允许进入低功耗，0-系统可以进入低功耗
static u16 g_auto_shutdown_timer = 0;
static void S_pen_app_select_btmode(u8 mode);

//----------------------------------
static const u8 S_pen_report_map[] = {
    0x05, 0x0C,        // Usage Page (Consumer)
    0x09, 0x01,        // Usage (Consumer Control)
    0xA1, 0x01,        // Collection (Application)
    0x85, COUSTOM_CONTROL_REPORT_ID,        //   Report ID (3)
    0x75, 0x10,        //   Report Size (16)
    0x95, 0x01,        //   Report Count (1)
    0x15, 0x01,        //   Logical Minimum (1)
    0x26, 0x8C, 0x02,  //   Logical Maximum (652)
    0x19, 0x01,        //   Usage Minimum (Consumer Control)
    0x2A, 0x8C, 0x02,  //   Usage Maximum (AC Send)
    0x81, 0x60,        //   Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x01,        //   Report Count (1)
    0x05, 0x0b,        //   Usage Page (Telephone)
    0x09, 0x21,        //   Usage (Flash)
    0x81, 0x02,        //   Input (Data,Var,Abs)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x07,        //   Report Count (15)
    0x81, 0x03,        //   Input (Const,Var,Abs)
    0xC0,              // End Collection
    0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
    0x09, 0x06,        // Usage (Keyboard)
    0xA1, 0x01,        // Collection (Application)
    0x85, KEYBOARD_REPORT_ID,         //   Report ID (1)
    0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
    0x19, 0xE0,        //   Usage Minimum (0xE0)
    0x29, 0xE7,        //   Usage Maximum (0xE7)
    0x15, 0x00,        //   Logical Minimum (0)
    0x25, 0x01,        //   Logical Maximum (1)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x08,        //   Report Count (8)
    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x01,        //   Report Count (1)
    0x75, 0x08,        //   Report Size (8)
    0x81, 0x01,        //   Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x03,        //   Report Count (3)
    0x75, 0x01,        //   Report Size (1)
    0x05, 0x08,        //   Usage Page (LEDs)
    0x19, 0x01,        //   Usage Minimum (Num Lock)
    0x29, 0x03,        //   Usage Maximum (Scroll Lock)
    0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
    0x95, 0x05,        //   Report Count (5)
    0x75, 0x01,        //   Report Size (1)
    0x91, 0x01,        //   Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
    0x95, 0x06,        //   Report Count (6)
    0x75, 0x08,        //   Report Size (8)
    0x15, 0x00,        //   Logical Minimum (0)
    0x26, 0xFF, 0x00,  //   Logical Maximum (255)
    0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
    0x19, 0x00,        //   Usage Minimum (0x00)
    0x2A, 0xFF, 0x00,  //   Usage Maximum (0xFF)
    0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              // End Collection

    // 91 bytes

    //  0x05, 0x0C,        // Usage Page (Consumer)
    // 0x09, 0x01,        // Usage (Consumer Control)
    // 0xA1, 0x01,        // Collection (Application)
    // 0x85, 0x03,        //   Report ID (1)
    // 0x09, 0xE9,        //   Usage (Volume Increment)
    // 0x09, 0xEA,        //   Usage (Volume Decrement)
    // 0x09, 0xB5,        //   Usage (Scan Next Track)
    // 0x09, 0xB6,        //   Usage (Scan Previous Track)
    // 0x09, 0xCD,        //   Usage (Play/Pause)
    // 0x09, 0x40,        //   Usage (Menu)
    // 0x09, 0x30,        //   Usage (Power)
    // 0x0a, 0x23, 0x02,  //   Usage (AC Home)
    // 0x15, 0x00,        //   Logical Minimum (0)
    // 0x25, 0x01,        //   Logical Maximum (1)
    // 0x75, 0x01,        //   Report Size (1)
    // 0x95, 0x08,        //   Report Count (16)
    // 0x81, 0x02,        //   Input (Data,Var,Abs)

    // 0x75, 0x01,        //   Report Size (1)
    // 0x95, 0x01,        //   Report Count (1)
    // 0x05, 0x0b,        //   Usage Page (Telephone)
    // 0x09, 0x21,        //   Usage (Flash)
    // 0x81, 0x02,        //   Input (Data,Var,Abs)
    // 0x75, 0x01,        //   Report Size (1)
    // 0x95, 0x07,        //   Report Count (15)
    // 0x81, 0x03,        //   Input (Const,Var,Abs)

    // 0xC0,              // End Collection
    // 35 bytes
};



//----------------------------------

static const u8 key_erase_press[8] = {0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00};    //橡皮擦(好像有点问题)
static const u8 key_erase_null[8] =  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};


static const u8 Consumer_ctrl_release[] =  {0x00, 0x00, 0x00, 0x00};   //消费类控制松手

//暂停接听


// 拒接

//息屏

//主界面

//返回键

//siri

//截屏

//上一曲

// 下一曲

int S_pen_send_hid_data(u16 report_id, u8 *data, u16 len)
{
    g_printf("HJY %s[line:%d,report_id:%d]\n",__func__,__LINE__, report_id);
    log_debug_hexdump(data, len);
    int ret = 0;
    if (bt_hid_mode == HID_MODE_EDR) {
#if TCFG_USER_EDR_ENABLE
        bt_comm_edr_sniff_clean();
        ret =edr_hid_data_send(report_id, data, len);
#endif
    } else {
#if TCFG_USER_BLE_ENABLE
        ret = ble_hid_data_send(report_id, data, len);
#endif
    }
    return ret;
}

// static const u8 key_pp_press[] = {0xcd, 0x00, 0x00, 0x00};
static const u8 key_pp_press[] = {0xcd, 0x00, 0x00, 0x00};
/**
 * @description: 音乐播放暂停，接听电话，挂断电话
 * @return {*}
 */
void ios_pp_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, key_pp_press, sizeof(key_pp_press));
    // os_time_dly(3);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));

}

static const u8 key_volume_inc_press[] = {0xe9, 0x00, 0x00, 0x00};
/**
 * @description: 音量加也可以用于拍照
 * @return {*}
 */
void ios_volume_inc_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, key_volume_inc_press, sizeof(key_volume_inc_press));
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));

}

static const u8 key_volume_dec_press[] = {0xeA, 0x00, 0x00, 0x00};
/**
 * @description: 音量减也可以用于拍照
 * @return {*}
 */
void ios_volume_dec_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, key_volume_dec_press, sizeof(key_volume_dec_press));
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));

}

static const u8 music_next_press[] = {0xB5, 0x00, 0x00, 0x00};
/**
 * @description: 下一曲
 * @return {*}
 */
void ios_music_next_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, music_next_press, sizeof(music_next_press));
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));

}

static const u8 music_prev_press[] = {0xB6, 0x00, 0x00, 0x00};
/**
 * @description: 上一曲
 * @return {*}
 */
void ios_music_prev_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, music_prev_press, sizeof(music_prev_press));
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));

}

/**
 * @description: 挂断电话,无电话的时候可以唤醒siri  iPhone11测试ok
 * @return {*}
 */
void ios_hangup_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, key_pp_press, sizeof(key_pp_press));
    os_time_dly(50);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));
}

static const u8 key_reject_press[] = {0x40, 0x00, 0x01, 0x00};
/**
 * @description: ios来电拒接
 * @return {*}
 */

void ios_reject_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, key_reject_press, sizeof(key_reject_press));
    os_time_dly(150);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));
}

static const u8 key_power_press[] = {0x30, 0x00, 0x00, 0x00};
/**
 * @description: 息屏，亮屏
 * @return {*}
 */

void ios_power_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, key_power_press, sizeof(key_power_press));
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));
}

/**
 * @description: siri 模拟长按电源键唤醒siri
 * @return {*}
 */

void ios_siri_ctrl_press(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, key_power_press, sizeof(key_power_press));
}

/**
 * @description: siri 模拟松开电源将结束唤醒
 * @return {*}
 */

void ios_siri_ctrl_release(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));
}


static const u8 key_home_press[] = {0x40, 0x00, 0x00, 0x00};
/**
 * @description: 主界面
 * @return {*}
 */

void ios_home_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, key_home_press, sizeof(key_home_press));
    S_pen_send_hid_data(COUSTOM_CONTROL_REPORT_ID, Consumer_ctrl_release, sizeof(Consumer_ctrl_release));
}

static u8 ios_pcs_on[] = {0x0A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
static u8 ios_pcs_up[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

/**
 * @description: 截屏
 * @return {*}
 */

void ios_pcs_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(KEYBOARD_REPORT_ID, ios_pcs_on, sizeof(ios_pcs_on));
    S_pen_send_hid_data(KEYBOARD_REPORT_ID, ios_pcs_up, sizeof(ios_pcs_up));
}
static const u8 key_revoke_press[8] = {0x08, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00};   //撤销操作
static const u8 key_revoke_null[8] =  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};


/**
 * @description: 撤销
 * @return {*}
 */

void ios_revoke_ctrl(void)
{
    g_printf("HJY %s[line:%d]\n",__func__,__LINE__);
    S_pen_send_hid_data(KEYBOARD_REPORT_ID, key_revoke_press, sizeof(key_revoke_press));
    S_pen_send_hid_data(KEYBOARD_REPORT_ID, key_revoke_null, sizeof(key_revoke_null));
}


//----------------------------------
static const edr_init_cfg_t S_pen_edr_config = {
    .page_timeout = 8000,
    .super_timeout = 8000,
    .io_capabilities = 3,
    .passkey_enable = 0,
    .authentication_req = 2,
    .oob_data = 0,
    .sniff_param = &S_pen_sniff_param,
    .class_type = BD_CLASS_KEYBOARD,
    .report_map = S_pen_report_map,
    .report_map_size = sizeof(S_pen_report_map),
};

//----------------------------------
static const ble_init_cfg_t S_pen_ble_config = {
    .same_address = 0,
    .appearance = BLE_APPEARANCE_HID_KEYBOARD,
    .report_map = S_pen_report_map,
    .report_map_size = sizeof(S_pen_report_map),
};

extern void p33_soft_reset(void);
extern void ble_hid_key_deal_test(u16 key_msg);
extern void ble_module_enable(u8 en);
static void S_pen_set_soft_poweroff(void);

/*************************************************************************************************/
/*!
 *  \brief      删除auto关机
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
static void S_pen_auto_shutdown_disable(void)
{
    log_info("----%s", __FUNCTION__);
    if (g_auto_shutdown_timer) {
        sys_timeout_del(g_auto_shutdown_timer);
    }
}

/*************************************************************************************************/
/*!
 *  \brief      测试一直发空键
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
#if HID_TEST_KEEP_SEND_EN
static u8 test_keep_send_start = 0;
extern int ble_hid_timer_handle;
extern int edr_hid_timer_handle;
extern int ble_hid_data_send(u8 report_id, u8 *data, u16 len);
void S_pen_test_keep_send_data(void)
{
    static const u8 test_data_000[8] = {0, 0, 0, 0};
    void (*hid_data_send_pt)(u8 report_id, u8 * data, u16 len) = NULL;

    if (!test_keep_send_start) {
        return;
    }

    if (bt_hid_mode == HID_MODE_EDR) {
#if TCFG_USER_EDR_ENABLE
        hid_data_send_pt = edr_hid_data_send;
        bt_comm_edr_sniff_clean();
#endif
    } else {
#if TCFG_USER_BLE_ENABLE
        hid_data_send_pt = ble_hid_data_send;
#endif
    }
    hid_data_send_pt(1, test_data_000, sizeof(test_data_000));
}

/*************************************************************************************************/
/*!
 *  \brief      初始化测试发送
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
void S_pen_test_keep_send_init(void)
{
    if (bt_hid_mode == HID_MODE_BLE) {
#if TCFG_USER_BLE_ENABLE
        log_info("###keep test ble\n");
        ble_hid_timer_handle = sys_s_hi_timer_add((void *)0, S_pen_test_keep_send_data, 10);
#endif
    } else {
#if TCFG_USER_EDR_ENABLE
        log_info("###keep test edr\n");
        edr_hid_timer_handle = sys_s_hi_timer_add((void *)0, S_pen_test_keep_send_data, 10);
#endif
    }
}
#endif


/*************************************************************************************************/
/*!
 *  \brief      按键处理
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
static void S_pen_app_key_deal_test(u8 key_type, u8 key_value)
{
    static u8 volume_control = 0;
    g_printf("HJY %s[line:%d](key_type:%d,key_value:%d)\n",__func__,__LINE__, key_type, key_value);


    switch (key_value)
    {
    case TCFG_ADKEY_VALUE0:
        /* code */
        switch (key_type)
        {
        case KEY_EVENT_CLICK:
            /* code */
            // ios_pp_ctrl();
            // ios_hangup_ctrl();
            // ios_pcs_ctrl();
            ios_revoke_ctrl();

            break;

        case KEY_EVENT_LONG:
            /* code */
            break;

        case KEY_EVENT_HOLD:
            /* code */
            break;
        case KEY_EVENT_UP:
            /* code */
            break;

        default:
            break;
        }
        break;
    case TCFG_ADKEY_VALUE1:
        /* code */
        switch (key_type)
        {
        case KEY_EVENT_CLICK:
            /* code */
            // ios_volume_inc_ctrl();
            ios_reject_ctrl();
            break;

        case KEY_EVENT_LONG:
            /* code */
            break;

        case KEY_EVENT_HOLD:
            /* code */
            break;
        case KEY_EVENT_UP:
            /* code */
            break;

        default:
            break;
        }
        break;
    case TCFG_ADKEY_VALUE2:
        /* code */
        switch (key_type)
        {
        case KEY_EVENT_CLICK:
            /* code */
            // ios_volume_dec_ctrl();
            ios_power_ctrl();
            break;

        case KEY_EVENT_LONG:
            /* code */
            break;

        case KEY_EVENT_HOLD:
            /* code */
            break;
        case KEY_EVENT_UP:
            /* code */
            break;

        default:
            break;
        }
        break;
    case TCFG_ADKEY_VALUE3:
        /* code */
        switch (key_type)
        {
        case KEY_EVENT_CLICK:
            /* code */
            // ios_music_next_ctrl();
            break;

        case KEY_EVENT_LONG:
            ios_siri_ctrl_press();
            /* code */
            break;

        case KEY_EVENT_HOLD:
            /* code */
            break;
        case KEY_EVENT_UP:
            /* code */
            ios_siri_ctrl_release();
            break;

        default:
            break;
        }
        break;
    case TCFG_ADKEY_VALUE4:
        /* code */
        switch (key_type)
        {
        case KEY_EVENT_CLICK:
            /* code */
            // ios_music_prev_ctrl();
            ios_home_ctrl();
            break;

        case KEY_EVENT_LONG:
            /* code */
            break;

        case KEY_EVENT_HOLD:
            /* code */
            break;
        case KEY_EVENT_UP:
            /* code */
            break;

        default:
            break;
        }
        break;

    default:
        break;
    }


}

/*************************************************************************************************/
/*!
 *  \brief      绑定信息 VM读写操作
 *
 *  \param      [in]rw_flag: 0-read vm,1--write
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
typedef struct {
    u16 head_tag;
    u8  mode;
} hid_vm_cfg_t;

#define	HID_VM_HEAD_TAG (0x3AA3)
static void S_pen_vm_deal(u8 rw_flag)
{
    hid_vm_cfg_t info;
    int ret;
    int vm_len = sizeof(hid_vm_cfg_t);

    log_info("-hid_info vm_do:%d\n", rw_flag);
    memset(&info, 0, vm_len);

    if (rw_flag == 0) {
        bt_hid_mode = HID_MODE_NULL;
        ret = syscfg_read(CFG_AAP_MODE_INFO, (u8 *)&info, vm_len);
        if (!ret) {
            log_info("-null--\n");
        } else {
            if (HID_VM_HEAD_TAG == info.head_tag) {
                log_info("-exist--\n");
                log_info_hexdump((u8 *)&info, vm_len);
                bt_hid_mode = info.mode;
            }
        }

        if (HID_MODE_NULL == bt_hid_mode) {
#if TCFG_USER_BLE_ENABLE
            bt_hid_mode = HID_MODE_BLE;
#else
            bt_hid_mode = HID_MODE_EDR;
#endif
        } else {
            if (!TCFG_USER_BLE_ENABLE) {
                bt_hid_mode = HID_MODE_EDR;
            }

            if (!TCFG_USER_EDR_ENABLE) {
                bt_hid_mode = HID_MODE_BLE;
            }

            if (bt_hid_mode != info.mode) {
                log_info("-write00--\n");
                info.mode = bt_hid_mode;
                syscfg_write(CFG_AAP_MODE_INFO, (u8 *)&info, vm_len);
            }
        }
    } else {
        info.mode = bt_hid_mode;
        info.head_tag = HID_VM_HEAD_TAG;
        syscfg_write(CFG_AAP_MODE_INFO, (u8 *)&info, vm_len);
        log_info("-write11--\n");
        log_info_hexdump((u8 *)&info, vm_len);
    }
}

/*************************************************************************************************/
/*!
 *  \brief      进入软关机
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
static void S_pen_set_soft_poweroff(void)
{
    log_info("S_pen_set_soft_poweroff\n");
    is_S_pen_active = 1;

#if TCFG_USER_BLE_ENABLE
    btstack_ble_exit(0);
#endif

#if TCFG_USER_EDR_ENABLE
    btstack_edr_exit(0);
#endif

#if (TCFG_USER_EDR_ENABLE || TCFG_USER_BLE_ENABLE)
    //延时300ms，确保BT退出链路断开
    sys_timeout_add(NULL, power_set_soft_poweroff, WAIT_DISCONN_TIME_MS);
#else
    power_set_soft_poweroff();
#endif
}

static void S_pen_timer_handle_test(void)
{
    log_info("not_bt");
}

/*************************************************************************************************/
/*!
 *  \brief      app 入口
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
extern void bt_pll_para(u32 osc, u32 sys, u8 low_power, u8 xosc);
static void S_pen_app_start()
{
    log_info("=======================================");
    log_info("-------------HID DEMO-----------------");
    log_info("=======================================");
    log_info("app_file: %s", __FILE__);

    clk_set("sys", BT_NORMAL_HZ);

    //有蓝牙
#if (TCFG_USER_EDR_ENABLE || TCFG_USER_BLE_ENABLE)
    u32 sys_clk =  clk_get("sys");
    bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0);

#if TCFG_USER_EDR_ENABLE
    btstack_edr_start_before_init(&S_pen_edr_config, 0);
#endif

#if TCFG_USER_BLE_ENABLE
    btstack_ble_start_before_init(&S_pen_ble_config, 0);
    /* le_hogp_set_reconnect_adv_cfg(ADV_IND, 5000); */
    le_hogp_set_reconnect_adv_cfg(ADV_DIRECT_IND_LOW, 5000);
#endif

    btstack_init();

#else
    //no bt,to for test
    sys_timer_add(NULL, S_pen_timer_handle_test, 1000);
#endif

    /* 按键消息使能 */
    sys_key_event_enable();

#if (TCFG_HID_AUTO_SHUTDOWN_TIME)
    //无操作定时软关机
    g_auto_shutdown_timer = sys_timeout_add(NULL, S_pen_set_soft_poweroff, TCFG_HID_AUTO_SHUTDOWN_TIME * 1000);
#endif
}


/*************************************************************************************************/
/*!
 *  \brief      app  状态处理
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
static int S_pen_state_machine(struct application *app, enum app_state state, struct intent *it)
{
    switch (state) {
    case APP_STA_CREATE:
        break;
    case APP_STA_START:
        if (!it) {
            break;
        }
        switch (it->action) {
        case ACTION_STYLUS_PEN:
            S_pen_app_start();
            break;
        }
        break;
    case APP_STA_PAUSE:
        break;
    case APP_STA_RESUME:
        break;
    case APP_STA_STOP:
        break;
    case APP_STA_DESTROY:
        log_info("APP_STA_DESTROY\n");
        break;
    }

    return 0;
}

/*************************************************************************************************/
/*!
 *  \brief      蓝牙HCI事件消息处理
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
static int S_pen_bt_hci_event_handler(struct bt_event *bt)
{
    //对应原来的蓝牙连接上断开处理函数  ,bt->value=reason
    log_info("----%s reason %x %x", __FUNCTION__, bt->event, bt->value);

#if TCFG_USER_EDR_ENABLE
    bt_comm_edr_hci_event_handler(bt);
#endif

#if TCFG_USER_BLE_ENABLE
    bt_comm_ble_hci_event_handler(bt);
#endif

    return 0;
}

/*************************************************************************************************/
/*!
 *  \brief      蓝牙连接状态事件消息处理
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
static int S_pen_bt_connction_status_event_handler(struct bt_event *bt)
{
    log_info("----%s %d", __FUNCTION__, bt->event);


    switch (bt->event) {
    case BT_STATUS_INIT_OK:
        /*
         * 蓝牙初始化完成
         */
        log_info("BT_STATUS_INIT_OK\n");

        S_pen_vm_deal(0);//bt_hid_mode read for VM

        //根据模式执行对应蓝牙的初始化
        if (bt_hid_mode == HID_MODE_BLE) {
#if TCFG_USER_BLE_ENABLE
            btstack_ble_start_after_init(0);
#endif
        } else {
#if TCFG_USER_EDR_ENABLE
            btstack_edr_start_after_init(0);
#endif
        }

        S_pen_app_select_btmode(HID_MODE_INIT);//

#if HID_TEST_KEEP_SEND_EN
        S_pen_test_keep_send_init();
#endif
        break;

    default:
#if TCFG_USER_EDR_ENABLE
        bt_comm_edr_status_event_handler(bt);
#endif

#if TCFG_USER_BLE_ENABLE
        bt_comm_ble_status_event_handler(bt);
#endif
        break;
    }
    return 0;
}

/*************************************************************************************************/
/*!
 *  \brief      蓝牙公共消息处理
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
static int S_pen_bt_common_event_handler(struct bt_event *bt)
{
    log_info("----%s reason %x %x", __FUNCTION__, bt->event, bt->value);

    switch (bt->event) {
    case COMMON_EVENT_EDR_REMOTE_TYPE:
        log_info(" COMMON_EVENT_EDR_REMOTE_TYPE,%d \n", bt->value);
        break;

    case COMMON_EVENT_BLE_REMOTE_TYPE:
        log_info(" COMMON_EVENT_BLE_REMOTE_TYPE,%d \n", bt->value);
        break;

    case COMMON_EVENT_SHUTDOWN_DISABLE:
        S_pen_auto_shutdown_disable();
        break;

    default:
        break;

    }
    return 0;
}

/*************************************************************************************************/
/*!
 *  \brief      按键事件处理
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
static void S_pen_key_event_handler(struct sys_event *event)
{
    /* u16 cpi = 0; */
    u8 event_type = 0;
    u8 key_value = 0;

    if (event->arg == (void *)DEVICE_EVENT_FROM_KEY) {
        event_type = event->u.key.event;
        key_value = event->u.key.value;
        log_info("app_key_evnet: %d,%d\n", event_type, key_value);
        S_pen_app_key_deal_test(event_type, key_value);
    }
}

/*************************************************************************************************/
/*!
 *  \brief      app 线程事件处理
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
static int S_pen_event_handler(struct application *app, struct sys_event *event)
{
#if (TCFG_HID_AUTO_SHUTDOWN_TIME)
    //重置无操作定时计数
    if (event->type != SYS_DEVICE_EVENT || DEVICE_EVENT_FROM_POWER != event->arg) { //过滤电源消息
        sys_timer_modify(g_auto_shutdown_timer, TCFG_HID_AUTO_SHUTDOWN_TIME * 1000);
    }
#endif

#if TCFG_USER_EDR_ENABLE
    bt_comm_edr_sniff_clean();
#endif

    switch (event->type) {
    case SYS_KEY_EVENT:
        S_pen_key_event_handler(event);
        return 0;

    case SYS_BT_EVENT:
#if (TCFG_USER_EDR_ENABLE || TCFG_USER_BLE_ENABLE)
        if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) {
            S_pen_bt_connction_status_event_handler(&event->u.bt);
        } else if ((u32)event->arg == SYS_BT_EVENT_TYPE_HCI_STATUS) {
            S_pen_bt_hci_event_handler(&event->u.bt);
        } else if ((u32)event->arg == SYS_BT_EVENT_FORM_COMMON) {
            return S_pen_bt_common_event_handler(&event->u.dev);
        }
#endif
        return 0;

    case SYS_DEVICE_EVENT:
        if ((u32)event->arg == DEVICE_EVENT_FROM_POWER) {
            return app_power_event_handler(&event->u.dev, S_pen_set_soft_poweroff);
        }
#if TCFG_CHARGE_ENABLE
        else if ((u32)event->arg == DEVICE_EVENT_FROM_CHARGE) {
            app_charge_event_handler(&event->u.dev);
        }
#endif
        return 0;

    default:
        return 0;
    }

    return 0;
}

/*************************************************************************************************/
/*!
 *  \brief      切换蓝牙模式
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note      切换模式,重启
 */
/*************************************************************************************************/
static void S_pen_app_select_btmode(u8 mode)
{
    if (mode != HID_MODE_INIT) {
        if (bt_hid_mode == mode) {
            return;
        }
        bt_hid_mode = mode;
    } else {
        //init start
    }

    log_info("###### %s: %d,%d\n", __FUNCTION__, mode, bt_hid_mode);

    if (bt_hid_mode == HID_MODE_BLE) {
        //ble
        log_info("---------app select ble--------\n");
        if (!STACK_MODULES_IS_SUPPORT(BT_BTSTACK_LE) || !BT_MODULES_IS_SUPPORT(BT_MODULE_LE)) {
            log_info("not surpport ble,make sure config !!!\n");
            ASSERT(0);
        }

#if TCFG_USER_EDR_ENABLE
        //close edr
        bt_comm_edr_mode_enable(0);
#endif

#if TCFG_USER_BLE_ENABLE
        if (mode == HID_MODE_INIT) {
            ble_module_enable(1);
        }
#endif

    } else {
        //edr
        log_info("---------app select edr--------\n");
        if (!STACK_MODULES_IS_SUPPORT(BT_BTSTACK_CLASSIC) || !BT_MODULES_IS_SUPPORT(BT_MODULE_CLASSIC)) {
            log_info("not surpport edr,make sure config !!!\n");
            ASSERT(0);
        }

#if TCFG_USER_BLE_ENABLE
        //close ble
        ble_module_enable(0);
#endif

#if TCFG_USER_EDR_ENABLE
        if (mode == HID_MODE_INIT) {
            if (!bt_connect_phone_back_start()) {
                bt_wait_phone_connect_control(1);
            }
        }
#endif

    }

    S_pen_vm_deal(1);
}

/*************************************************************************************************/
/*!
 *  \brief      注册控制是否进入sleep
 *
 *  \param      [in]
 *
 *  \return
 *
 *  \note
 */
/*************************************************************************************************/
//-----------------------
//system check go sleep is ok
static u8 S_pen_app_idle_query(void)
{
    return !is_S_pen_active;
}

REGISTER_LP_TARGET(app_S_pen_lp_target) = {
    .name = "app_S_pen_deal",
    .is_idle = S_pen_app_idle_query,
};


static const struct application_operation app_S_pen_ops = {
    .state_machine  = S_pen_state_machine,
    .event_handler  = S_pen_event_handler,
};

/*
 * 注册模式
 */
REGISTER_APPLICATION(app_S_pen) = {
    .name   = "S_pen",
    .action	= ACTION_STYLUS_PEN,
    .ops    = &app_S_pen_ops,
    .state  = APP_STA_DESTROY,
};


#endif
